package me.buick.util.snmp.core.dao.impl.snmp;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import me.buick.util.snmp.core.SupportedOS;
import me.buick.util.snmp.core.dao.NetworkIfInfoDAO;
import me.buick.util.snmp.core.pojo.NetworkInfoPojo;

import org.opengoss.snmphibernate.api.ISnmpSession;



/**
 * 
 * Version 1.0
 * 
 * @author buick
 *
 */

public class SNMPNetworkInfoDAO implements NetworkIfInfoDAO, IPollable{
	
	ISnmpSession session = null;
	SupportedOS  os	     = SupportedOS.Linux;
	
	long		 lastPolled;
	Map<String, NetworkInfoPojo> networkIfInfoPojoFinalResult;
	Map<String, NetworkInfoPojo> networkIfInfoPojoPreResult;
	
	public SNMPNetworkInfoDAO(SupportedOS os, ISnmpSession session){
		this.session = session;
		this.os		 = os;
	}
	
	public Map<String, NetworkInfoPojo> getNetworkInfo(){
		if(this.networkIfInfoPojoFinalResult != null){
			return this.networkIfInfoPojoFinalResult;
		}
		return extractNetworkIfInfo();
	}

	private Map<String, NetworkInfoPojo> extractNetworkIfInfo() {
		if(this.os == SupportedOS.Windows){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrIfEntry> networkIOResultList = null;
			try{
				networkIOResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrIfEntry.class);
			}catch(Exception e){
				e.printStackTrace();
			}
			Map<String, NetworkInfoPojo> tempNetworkIO = new HashMap<String, NetworkInfoPojo>();
			for(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrIfEntry ifEntry : networkIOResultList){
				String ifDescr = ifEntry.getIfDescr();
				if(ifEntry.getIfType() == 6){
					NetworkInfoPojo pojo = new NetworkInfoPojo();
					pojo.setIfDescr(ifDescr);
					pojo.setIfIndex(ifEntry.getIfIndex());
					pojo.setIfTotalInBytes(ifEntry.getIfIn());
					pojo.setIfTotalOutBytes(ifEntry.getIfOut());
					tempNetworkIO.put(ifDescr, pojo);
				}
			}
			return tempNetworkIO;
		}else if(this.os == SupportedOS.Linux){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrIfEntry> networkIOResultList = null;
			try{
				networkIOResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrIfEntry.class);
			}catch(Exception e){
				e.printStackTrace();
			}
			Map<String, NetworkInfoPojo> tempNetworkIO = new HashMap<String, NetworkInfoPojo>();
			for(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrIfEntry ifEntry : networkIOResultList){
				String ifDescr = ifEntry.getIfDescr();
				if(ifDescr != null && (ifDescr.toLowerCase().contains("eth"))){
					NetworkInfoPojo pojo = new NetworkInfoPojo();
					pojo.setIfDescr(ifDescr);
					pojo.setIfIndex(ifEntry.getIfIndex());
					pojo.setIfTotalInBytes(ifEntry.getIfIn());
					pojo.setIfTotalOutBytes(ifEntry.getIfOut());
					tempNetworkIO.put(ifDescr, pojo);
				}
			}
			return tempNetworkIO;
		}
		return null;
	}

	public void poll(long interval) {
		if(this.networkIfInfoPojoPreResult == null){
			this.lastPolled = System.currentTimeMillis();
			this.networkIfInfoPojoPreResult = this.extractNetworkIfInfo();
		}else{
			
			long now  = System.currentTimeMillis();
			
			Map<String, NetworkInfoPojo> nifioPojo = new HashMap<String, NetworkInfoPojo>();
			Map<String, NetworkInfoPojo> preNIFIO = this.networkIfInfoPojoPreResult;
			Map<String, NetworkInfoPojo> networkIfInfoPojoPostResult = this.extractNetworkIfInfo();
			for (String ifName : networkIfInfoPojoPostResult.keySet()) {
				NetworkInfoPojo prePojo = preNIFIO.get(ifName);
				NetworkInfoPojo postPojo = networkIfInfoPojoPostResult.get(ifName);
				if (prePojo != null) {
					long diffIn = (postPojo.getIfTotalInBytes() - prePojo.getIfTotalInBytes());
					long diffOut = (postPojo.getIfTotalOutBytes() - prePojo.getIfTotalOutBytes());
					NetworkInfoPojo nifPojo = new NetworkInfoPojo();
					if(diffIn > 0 || diffOut > 0){
						nifPojo.setIfDescr(postPojo.getIfDescr());
						nifPojo.setIfIndex(postPojo.getIfIndex());
						nifPojo.setIfTotalInBytes(diffIn);
						nifPojo.setIfTotalOutBytes(diffOut);
						nifPojo.setIfInBytesPS((long)(diffIn/(double)15));
						nifPojo.setIfOutBytesPS((long)(diffOut/(double)15));
						nifioPojo.put(ifName, nifPojo);
					}else{
						nifioPojo.put(ifName, nifPojo);
					}
				} else {
					continue;
				}
			}
			this.networkIfInfoPojoFinalResult = nifioPojo;
			this.networkIfInfoPojoPreResult   = networkIfInfoPojoPostResult;
			this.lastPolled = now;

		}
	}
}
